package com.sophie;


import com.alibaba.fastjson.JSON;
import com.sophie.rule.MockRule;
import com.sophie.rule.MockRuleFactory;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

import java.util.Collection;

@Data
public class MockField {
    /**
     * mockField 所属的 template
     */
    private String mockTemplate;
    /**
     * 字段名
     */
    private String name;
    /**
     * 原字段名，形如：字段名|规则串
     */
    private String originName;
    /**
     * 规则串
     */
    private String ruleStr;
    /**
     * mock规则
     */
    private MockRule mockRule;
    /**
     * 原始的基础值
     */
    private String baseValue;
    /**
     * 原始的基础值的类型
     */
    private Class baseValueType;

    public static MockField parse(String mockTemplate, String nameRule, String value) {
        MockField mockField = new MockField();
        mockField.mockTemplate = mockTemplate;
        mockField.originName = nameRule;
        String[] arr = nameRule.split("\\|");
        if (arr.length > 2) {
            throw new IllegalArgumentException("mock模板配置错误：" + nameRule);
        }
        //如果@开头，就是mock规则
        if (isMockRule(arr[0])) {
            mockField.name = StringUtils.substringAfter(arr[0], "@");
        }
        //非@开头的是返回写好的静态数据
        else {
            mockField.name = arr[0];
        }
        if (arr.length >= 2) {
            mockField.ruleStr = arr[1];
        }
        mockField.baseValue = value;
        mockField.baseValueType = parseMockType(mockField.baseValue);
        mockField.mockRule = MockRuleFactory.find(mockField);

        return mockField;
    }

    /**
     * 从用户输入的mock规则中解析出MockField
     *
     * @param name         返回参数名
     * @param mockTemplate 用户输入的mock规则
     * @return
     */
    public static MockField parseFromString(String name, String mockTemplate) {
        MockField mockField = new MockField();
        mockField.mockTemplate = mockTemplate;
        mockField.name = name;
        StringBuffer originName = new StringBuffer(name);
        String baseValue = mockTemplate;
        String ruleStr = "";
        //如果mock规则以@开头，则为mock规则
        if (isMockRule(mockTemplate)) {
            //并且其中有限制返回数据的取值个数，用（）包裹的参数
            if (StringUtils.contains(mockTemplate, "(")) {
                //取出当前参数的类型，如@str(1-3)"xx"，取出类型str
                String type = StringUtils.substringBetween(mockTemplate, "@", "(");
                ruleStr = StringUtils.substringBetween(mockTemplate, "(", ")");
                if (StringUtils.equals(type, "str")) {
                    baseValue = StringUtils.substringAfter(mockTemplate, ")");
                } else if (StringUtils.equals(type, "num")) {
                    if (mockTemplate.contains("."))
                        baseValue = StringUtils.substringBetween(mockTemplate, "-", ".");
                    else baseValue=StringUtils.substringBetween(mockTemplate,"-",")");
                }
            }
            //若为@boolean
            else if (StringUtils.equals("@boolean", mockTemplate)) {
                ruleStr = "@random";
                baseValue = "true";
            }
            originName.append("|").append(ruleStr);
            mockField.originName = originName.toString();
            mockField.ruleStr = ruleStr;

        } else mockField.originName = name;
        mockField.baseValue = baseValue;
        mockField.baseValueType = parseMockType(mockField.baseValue);
        mockField.mockRule = MockRuleFactory.find(mockField);
        return mockField;
    }


    public static boolean isMockRule(String nameRule) {
        return nameRule.startsWith("@");
    }

    /**
     * 解析 baseValue 对应的 Class。解析的顺序与 MockRule 的应用顺序有关。<br/>
     * String.class 放到最后，属于默认类型。
     *
     * @param baseValue
     * @return
     */
    private static Class parseMockType(String baseValue) {
        // 1. int
        try {
            Integer.valueOf(baseValue);
            return int.class;
        } catch (NumberFormatException e) {
        }

        // 2. boolean
        if ("true".equals(baseValue) || "false".equals(baseValue)) {
            return boolean.class;
        }

        // 3. 集合类型
        try {
            JSON.parseArray(baseValue);
            return Collection.class;
        } catch (Exception e) {
        }

        // 4. Object
        try {
            JSON.parseObject(baseValue);
            return Object.class;
        } catch (Exception e) {
        }

        // 5. Sting
        return String.class;
    }

    public Object generateMockData() {
        return this.mockRule.generateMockData();
    }

    /**
     * 重写 hashCode 和 equals 的目的是在 MockDataContext 中需要使用 MockField 做为 Map 的 key
     */
    @Override
    public int hashCode() {
        return 31 * mockTemplate.hashCode();
    }

    @Override
    public boolean equals(Object other) {
        if (other == null) {
            return false;
        }
        if (!(other instanceof MockField)) {
            return false;
        }

        MockField mockField = (MockField) other;
        if (mockField.mockTemplate != null && this.mockTemplate != null && mockField.mockTemplate.equals(this.mockTemplate)
                && mockField.originName != null && this.originName != null && mockField.originName.equals(this.originName)
                && mockField.baseValue != null && this.baseValue != null && mockField.baseValue.equals(this.baseValue)) {
            return true;
        }

        return false;
    }
}
